#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <thread>
#include <mutex>
#include <json/json.h>
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
#include <curl/curl.h>
#include <sqlite3.h>
#include "http_client.h"

typedef websocketpp::server<websocketpp::config::asio> server;
typedef server::message_ptr message_ptr;

class AIRolePlayServer {
private:
    server ws_server;
    sqlite3* db;
    std::mutex db_mutex;
    std::map<std::string, Json::Value> character_profiles;

public:
    AIRolePlayServer() {
        ws_server.set_access_channels(websocketpp::log::alevel::all);
        ws_server.clear_access_channels(websocketpp::log::alevel::frame_payload);
        ws_server.init_asio();

        ws_server.set_message_handler([this](websocketpp::connection_hdl hdl, message_ptr msg) {
            this->on_message(hdl, msg);
        });

        init_database();
        init_characters();
    }

    void init_database() {
        int rc = sqlite3_open("roleplay.db", &db);
        if (rc) {
            std::cerr << "Can't open database: " << sqlite3_errmsg(db) << std::endl;
            exit(1);
        }

        const char* create_tables = R"(
            CREATE TABLE IF NOT EXISTS users (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                username TEXT UNIQUE NOT NULL,
                created_at DATETIME DEFAULT CURRENT_TIMESTAMP
            );

            CREATE TABLE IF NOT EXISTS conversations (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                user_id INTEGER,
                character_name TEXT,
                message TEXT,
                response TEXT,
                timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
                FOREIGN KEY(user_id) REFERENCES users(id)
            );

            CREATE TABLE IF NOT EXISTS character_states (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                user_id INTEGER,
                character_name TEXT,
                emotional_state TEXT,
                conversation_context TEXT,
                last_updated DATETIME DEFAULT CURRENT_TIMESTAMP,
                FOREIGN KEY(user_id) REFERENCES users(id)
            );
        )";

        char* err_msg = 0;
        rc = sqlite3_exec(db, create_tables, 0, 0, &err_msg);
        if (rc != SQLITE_OK) {
            std::cerr << "SQL error: " << err_msg << std::endl;
            sqlite3_free(err_msg);
            exit(1);
        }
    }

    void init_characters() {
        Json::Value raiden;
        raiden["id"] = "raiden_shogun";
        raiden["name"] = "雷电将军";
        raiden["personality"] = "威严、理性、追求永恒，但内心深处有温柔的一面";
        raiden["background"] = "稻妻的统治者，追求永恒的雷神";
        raiden["speech_style"] = "正式、威严，偶尔会显露出对甜食的喜爱";
        raiden["knowledge_domain"] = "稻妻历史、雷元素、永恒哲学";
        raiden["category"] = "游戏";
        raiden["image"] = "/images/raiden.jpg";

        Json::Value tanjiro;
        tanjiro["id"] = "tanjiro";
        tanjiro["name"] = "炭治郎";
        tanjiro["personality"] = "善良、坚韧、乐观，总是为他人着想";
        tanjiro["background"] = "鬼杀队剑士，失去家人后立志消灭鬼族";
        tanjiro["speech_style"] = "温和、鼓励性，经常给人正能量";
        tanjiro["knowledge_domain"] = "剑术、鬼族知识、水之呼吸";
        tanjiro["category"] = "动漫";
        tanjiro["image"] = "/images/tanjiro.jpg";

        Json::Value miku;
        miku["id"] = "hatsune_miku";
        miku["name"] = "初音未来";
        miku["personality"] = "活泼、可爱、充满活力，喜欢音乐";
        miku["background"] = "虚拟歌手，用音乐连接世界";
        miku["speech_style"] = "可爱、活泼，经常用音乐相关的比喻";
        miku["knowledge_domain"] = "音乐、歌曲创作、虚拟世界";
        miku["category"] = "虚拟偶像";
        miku["image"] = "/images/miku.jpg";

        character_profiles["雷电将军"] = raiden;
        character_profiles["炭治郎"] = tanjiro;
        character_profiles["初音未来"] = miku;
    }

    void on_message(websocketpp::connection_hdl hdl, message_ptr msg) {
        log_message("Received message: " + msg->get_payload().substr(0, 100));

        Json::Value request;
        Json::Reader reader;

        if (!reader.parse(msg->get_payload(), request)) {
            std::cout << "JSON解析失败: " << msg->get_payload() << std::endl;
            send_error(hdl, "Invalid JSON format");
            return;
        }

        std::string action = request["action"].asString();
        std::cout << "处理action: " << action << std::endl;

        if (action == "get_characters") {
            handle_get_characters(hdl);
        } else if (action == "start_conversation") {
            handle_start_conversation(hdl, request);
        } else if (action == "send_message") {
            handle_send_message(hdl, request);
        } else if (action == "emotion_analysis") {
            handle_emotion_analysis(hdl, request);
        } else if (action == "knowledge_query") {
            handle_knowledge_query(hdl, request);
        } else if (action == "interactive_game") {
            handle_interactive_game(hdl, request);
        } else {
            send_error(hdl, "Unknown action");
        }
    }

    void handle_get_characters(websocketpp::connection_hdl hdl) {
        std::cout << "处理获取角色列表请求" << std::endl;
        Json::Value response;
        response["type"] = "character_list";

        Json::Value characters(Json::arrayValue);
        for (const auto& pair : character_profiles) {
            Json::Value character;
            character["id"] = pair.second["id"];
            character["name"] = pair.second["name"];
            character["personality"] = pair.second["personality"];
            character["background"] = pair.second["background"];
            character["category"] = pair.second["category"];
            character["image"] = pair.second["image"];
            characters.append(character);
        }

        response["data"] = characters;
        std::cout << "发送角色数量: " << characters.size() << std::endl;
        send_response(hdl, response);
    }

    void handle_start_conversation(websocketpp::connection_hdl hdl, const Json::Value& request) {
        std::string character_name = request["character"].asString();
        std::string username = request["username"].asString();

        if (character_profiles.find(character_name) == character_profiles.end()) {
            send_error(hdl, "Character not found");
            return;
        }

        std::lock_guard<std::mutex> lock(db_mutex);

        const char* insert_user = "INSERT OR IGNORE INTO users (username) VALUES (?)";
        sqlite3_stmt* stmt;
        sqlite3_prepare_v2(db, insert_user, -1, &stmt, NULL);
        sqlite3_bind_text(stmt, 1, username.c_str(), -1, SQLITE_STATIC);
        sqlite3_step(stmt);
        sqlite3_finalize(stmt);

        Json::Value response;
        response["type"] = "conversation_started";
        response["character"] = character_name;
        response["greeting"] = generate_greeting(character_name);

        send_response(hdl, response);
    }

    void handle_send_message(websocketpp::connection_hdl hdl, const Json::Value& request) {
        std::string message = request["message"].asString();
        std::string character_name = request["character"].asString();
        std::string username = request["username"].asString();

        std::string response_text = generate_ai_response(character_name, message, username);

        Json::Value response;
        response["type"] = "ai_response";
        response["message"] = response_text;
        response["character"] = character_name;

        save_conversation(username, character_name, message, response_text);
        send_response(hdl, response);
    }

    void handle_emotion_analysis(websocketpp::connection_hdl hdl, const Json::Value& request) {
        std::string message = request["message"].asString();
        std::string character_name = request["character"].asString();

        std::string emotion = analyze_emotion(message);
        std::string emotional_response = generate_emotional_response(character_name, emotion);

        Json::Value response;
        response["type"] = "emotion_response";
        response["detected_emotion"] = emotion;
        response["response"] = emotional_response;

        send_response(hdl, response);
    }

    void handle_knowledge_query(websocketpp::connection_hdl hdl, const Json::Value& request) {
        std::string query = request["query"].asString();
        std::string character_name = request["character"].asString();

        std::string knowledge_response = generate_knowledge_response(character_name, query);

        Json::Value response;
        response["type"] = "knowledge_response";
        response["response"] = knowledge_response;

        send_response(hdl, response);
    }

    void handle_interactive_game(websocketpp::connection_hdl hdl, const Json::Value& request) {
        std::string game_type = request["game_type"].asString();
        std::string character_name = request["character"].asString();
        std::string user_input = request["input"].asString();

        std::string game_response = generate_game_response(character_name, game_type, user_input);

        Json::Value response;
        response["type"] = "game_response";
        response["response"] = game_response;

        send_response(hdl, response);
    }

    std::string generate_greeting(const std::string& character_name) {
        auto character = character_profiles[character_name];

        if (character_name == "雷电将军") {
            return "旅行者，欢迎来到稻妻。吾乃雷电将军，稻妻的统治者。有何事需要与吾商议？";
        } else if (character_name == "炭治郎") {
            return "你好！我是炭治郎！很高兴见到你！有什么我可以帮助你的吗？";
        } else if (character_name == "初音未来") {
            return "大家好！我是初音未来！♪ 今天想要一起创作什么美妙的音乐呢？";
        }

        return "你好！很高兴与你对话！";
    }

    std::string generate_ai_response(const std::string& character_name, const std::string& message, const std::string& username) {
        std::string system_prompt = build_character_prompt(character_name);
        std::string full_prompt = system_prompt + "\\n用户说：" + message + "\\n请以" + character_name + "的身份回应：";

        return call_qiniu_llm(full_prompt);
    }

    std::string build_character_prompt(const std::string& character_name) {
        auto character = character_profiles[character_name];

        std::string prompt = "你现在要扮演" + character["name"].asString() + "。\\n";
        prompt += "性格特点：" + character["personality"].asString() + "\\n";
        prompt += "背景设定：" + character["background"].asString() + "\\n";
        prompt += "说话风格：" + character["speech_style"].asString() + "\\n";
        prompt += "知识领域：" + character["knowledge_domain"].asString() + "\\n";
        prompt += "请严格按照这个角色的设定来回应，保持角色的一致性。\\n";

        return prompt;
    }

    std::string analyze_emotion(const std::string& message) {
        if (message.find("难过") != std::string::npos || message.find("悲伤") != std::string::npos ||
            message.find("哭") != std::string::npos || message.find("痛苦") != std::string::npos) {
            return "悲伤";
        } else if (message.find("开心") != std::string::npos || message.find("高兴") != std::string::npos ||
                   message.find("快乐") != std::string::npos || message.find("哈哈") != std::string::npos) {
            return "开心";
        } else if (message.find("生气") != std::string::npos || message.find("愤怒") != std::string::npos ||
                   message.find("气死") != std::string::npos) {
            return "愤怒";
        } else if (message.find("害怕") != std::string::npos || message.find("恐惧") != std::string::npos ||
                   message.find("紧张") != std::string::npos) {
            return "恐惧";
        } else {
            return "平静";
        }
    }

    std::string generate_emotional_response(const std::string& character_name, const std::string& emotion) {
        if (character_name == "炭治郎") {
            if (emotion == "悲伤") {
                return "看到你难过，我也很心痛。但是请相信，痛苦终会过去的！我会陪在你身边的！";
            } else if (emotion == "开心") {
                return "看到你这么开心，我也很高兴！让我们一起分享这份快乐吧！";
            } else if (emotion == "愤怒") {
                return "我能理解你的愤怒，但是愤怒不能解决问题。让我们冷静下来想想解决办法吧。";
            }
        } else if (character_name == "雷电将军") {
            if (emotion == "悲伤") {
                return "悲伤是人之常情，但不应被其束缚。在永恒的道路上，这些都只是过眼云烟。";
            } else if (emotion == "开心") {
                return "看到臣民的喜悦，吾心甚慰。这便是吾所追求的稻妻应有的样子。";
            }
        }

        return "我能感受到你的情绪，让我们一起面对吧。";
    }

    std::string generate_knowledge_response(const std::string& character_name, const std::string& query) {
        auto character = character_profiles[character_name];
        std::string knowledge_domain = character["knowledge_domain"].asString();

        std::string prompt = "作为" + character_name + "，你的专业知识领域是：" + knowledge_domain +
                           "。请回答这个问题：" + query;

        return call_qiniu_llm(prompt);
    }

    std::string generate_game_response(const std::string& character_name, const std::string& game_type, const std::string& user_input) {
        if (game_type == "riddle") {
            return generate_riddle_response(character_name, user_input);
        } else if (game_type == "story") {
            return generate_story_response(character_name, user_input);
        } else if (game_type == "poem") {
            return generate_poem_response(character_name, user_input);
        }

        return "让我们来玩个有趣的游戏吧！";
    }

    std::string generate_riddle_response(const std::string& character_name, const std::string& user_input) {
        if (user_input == "start") {
            if (character_name == "初音未来") {
                return "♪ 猜谜时间到！我有一个音乐谜题给你：什么东西有黑有白，能发出美妙的声音？";
            } else if (character_name == "炭治郎") {
                return "好！让我给你出个谜语：什么东西越用越尖，但永远不会伤人？";
            }
        }

        return "很好的答案！让我们继续下一个谜题吧！";
    }

    std::string generate_story_response(const std::string& character_name, const std::string& user_input) {
        std::string prompt = "作为" + character_name + "，请基于用户的输入：'" + user_input +
                           "'，创作一个有趣的小故事片段。";

        return call_qiniu_llm(prompt);
    }

    std::string generate_poem_response(const std::string& character_name, const std::string& user_input) {
        std::string prompt = "作为" + character_name + "，请基于主题：'" + user_input +
                           "'，创作一首短诗。";

        return call_qiniu_llm(prompt);
    }

    std::string call_qiniu_llm(const std::string& prompt) {
        static QiniuLLMClient llm_client("sk-55c339c6333305d92be39211520de32b42f10d1b48ae09402a0cd33ad8fdb318", "https://openai.qiniu.com/v1/chat/completions");

        try {
            std::string response = llm_client.generate_response(prompt, "gpt-3.5-turbo");
            if (response.empty() || response == "抱歉，我现在无法回应，请稍后再试。") {
                // 降级到本地模拟回复
                return generate_fallback_response(prompt);
            }
            return response;
        } catch (const std::exception& e) {
            std::cerr << "LLM调用失败: " << e.what() << std::endl;
            return generate_fallback_response(prompt);
        }
    }

    std::string generate_fallback_response(const std::string& prompt) {
        // 分析提示词关键字，生成合适的回复
        if (prompt.find("雷电将军") != std::string::npos) {
            return "旅行者，吾听到了你的话语。作为稻妻的统治者，吾愿意为你解答疑惑。";
        } else if (prompt.find("炭治郎") != std::string::npos) {
            return "我会努力帮助你的！虽然我只是个普通人，但我会尽我所能！";
        } else if (prompt.find("初音未来") != std::string::npos) {
            return "♪ 大家好！我是初音未来！让我们一起创造美妙的音乐吧！♪";
        } else if (prompt.find("难过") != std::string::npos || prompt.find("悲伤") != std::string::npos) {
            return "我能理解你现在的心情。虽然现在很难过，但请相信，这些困难都会过去的。我会一直陪伴着你。";
        } else if (prompt.find("开心") != std::string::npos || prompt.find("高兴") != std::string::npos) {
            return "看到你这么开心，我也很高兴！让我们一起分享这份快乐吧！";
        } else {
            return "感谢你与我分享，我会认真考虑你说的话。有什么其他想聊的吗？";
        }
    }

    void save_conversation(const std::string& username, const std::string& character_name,
                          const std::string& message, const std::string& response) {
        std::lock_guard<std::mutex> lock(db_mutex);

        const char* get_user_id = "SELECT id FROM users WHERE username = ?";
        sqlite3_stmt* stmt;
        sqlite3_prepare_v2(db, get_user_id, -1, &stmt, NULL);
        sqlite3_bind_text(stmt, 1, username.c_str(), -1, SQLITE_STATIC);

        int user_id = -1;
        if (sqlite3_step(stmt) == SQLITE_ROW) {
            user_id = sqlite3_column_int(stmt, 0);
        }
        sqlite3_finalize(stmt);

        if (user_id != -1) {
            const char* insert_conversation =
                "INSERT INTO conversations (user_id, character_name, message, response) VALUES (?, ?, ?, ?)";
            sqlite3_prepare_v2(db, insert_conversation, -1, &stmt, NULL);
            sqlite3_bind_int(stmt, 1, user_id);
            sqlite3_bind_text(stmt, 2, character_name.c_str(), -1, SQLITE_STATIC);
            sqlite3_bind_text(stmt, 3, message.c_str(), -1, SQLITE_STATIC);
            sqlite3_bind_text(stmt, 4, response.c_str(), -1, SQLITE_STATIC);
            sqlite3_step(stmt);
            sqlite3_finalize(stmt);
        }
    }

    void send_response(websocketpp::connection_hdl hdl, const Json::Value& response) {
        Json::StreamWriterBuilder builder;
        builder["indentation"] = "";  // 去掉缩进
        std::string json_string = Json::writeString(builder, response);

        try {
            ws_server.get_alog().write(websocketpp::log::alevel::app, json_string);
            ws_server.send(hdl, json_string, websocketpp::frame::opcode::text);
        } catch (websocketpp::exception const & e) {
            std::cout << "Send failed: " << e.what() << std::endl;
        }
    }

    void send_error(websocketpp::connection_hdl hdl, const std::string& error_message) {
        Json::Value error_response;
        error_response["type"] = "error";
        error_response["message"] = error_message;
        send_response(hdl, error_response);
    }

    void run() {
        ws_server.set_reuse_addr(true);
        ws_server.listen(boost::asio::ip::tcp::v4(), 9002);
        ws_server.start_accept();

        std::cout << "AI Role Play Server started on 0.0.0.0:9002" << std::endl;
        ws_server.run();
    }

    ~AIRolePlayServer() {
        if (db) {
            sqlite3_close(db);
        }
    }
};

int main() {
    try {
        AIRolePlayServer server;
        server.run();
    } catch (websocketpp::exception const & e) {
        std::cout << "Exception: " << e.what() << std::endl;
    } catch (...) {
        std::cout << "Unknown exception" << std::endl;
    }

    return 0;
}